import torch
import numpy as np

# 创建张量
# 1.直接创建，torch.tensor()
# flag = True
flag = False
if flag:
    t = torch.tensor([[0, 5, 4, 5, 8, 9], [2, 7, 5, 8, 8, 6]])
    # t = torch.tensor(arr, device='cuda')

    print(t)

# 2.直接创建，torch.from_numpy(ndarray)
# 创建的Tensor和原来的ndarray共享内存
# flag = True
flag = False
if flag:
    arr = np.array([[1, 3, 3], [4, 5, 6]])
    t = torch.from_numpy(arr)

    print(t)

    arr[0, 1] = 5
    print(t)

# 依据数值创建
# 3.创建全0张量
# flag = True
flag = False
if flag:
    out_t = torch.tensor([1])
    print("out_t:{}, id={}".format(out_t, id(out_t)))
    # 将张量t赋值给out_t,二者共享内存
    t = torch.zeros((3, 3), out=out_t)
    print("t:{}\nout_t:{}".format(t, out_t))
    print(id(t), id(out_t), id(t) == id(out_t))

    # 按照input的形状创建全0张量
    t1 = torch.zeros_like(out_t)
    print(t1)

# 4.创建全1张量
# flag = True
flag = False
if flag:
    out_t = torch.tensor([1])
    print(out_t)
    # 将张量t赋值给out_t,二者共享内存
    t = torch.ones((3, 3), out=out_t)
    print(out_t)
    print(id(t), id(out_t), id(t) == id(out_t))

    # 按照input的形状创建全1张量
    t1 = torch.ones_like(out_t)
    print(t1)

# 5.创建自定义张量
# flag = True
flag = False
if flag:
    t = torch.full((3, 3), 5.)
    print(t)

    # 按照input的形状创建自定义张量
    t1 = torch.full_like(t, 6)
    print(t1)

# 6.创建等差1维张量
# flag = True
flag = False
if flag:
    # 创建步长为2的等差数列1维张量,范围[0,10)
    t = torch.arange(0, 10, 2)
    print(t)

# 7.创建均分1维张量
# torch.linspace(start, end, steps=100, out=None)
# flag = True
flag = False
if flag:
    # 创建均分1维张量，范围[0,10]，长度默认100
    t = torch.linspace(0, 10)
    t1 = torch.linspace(0, 10, steps=5)

    print(t)
    print(t1)

# 8.创建对数均分1维张量
# torch.logspace(start, end, steps=100, base=10, out=None)
# 在区间 base^(start)和 base^(end) 上按照 [start,end] 均分的 steps 个点
# flag = True
flag = False
if flag:
    # 创建对数均分1维张量，范围[0,10]，长度默认100，底默认10
    t = torch.logspace(0, 4, steps=2, base=2)
    print(t)

# 9.创建单位对角阵张量
# torch.eye(n,m=None)
# flag = True
flag = False
if flag:
    t = torch.eye(3)
    print(t)

# 依概率分布创建张量
# 1.正态分布（高斯分布）
'''
torch.normal(mean, # 均值
             std, # 标准差
             out=None)
'''
# flag = True
flag = False
if flag:
    # mean:张量 std:张量
    # 此时mean和std维数（n）要相等，由他们生成n个正态分布，
    # 从每个分布随机抽取一个数，组成一个1维张量
    mean = torch.arange(1, 5, dtype=torch.float)
    std = torch.arange(1, 5, dtype=torch.float)
    t_normal = torch.normal(mean, std)
    print(t_normal)

    # mean:标量 std:标量
    # 生成1个分布，随机取size大小的数
    # 1维
    t_normal = torch.normal(0, 1, size=(4,))
    # 4*2维
    t_normal1 = torch.normal(0, 1, size=(4, 2))
    print(t_normal)
    print(t_normal1)

    # mean:张量 std:标量
    # 生成同mean大小个分布，所有分布的std相同
    # 从每个分布随机抽取一个数，组成一个1维张量
    # mean:标量 std:张量 同理
    mean = torch.arange(1, 5, dtype=torch.float)
    # 1维
    t_normal = torch.normal(mean, 1)
    print(t_normal)

# 2.标准正态分布(mean=0, std=1)
'''
torch.randn(*size
            out=None,
            dtype=None,
            layout=torch.strided,
            device=None,
            requires_grad=Flase)
'''
# flag = True
flag = False
if flag:
    # 由于均值和标准差都确定了，只需size就可以创建
    t_normal = torch.randn(2, 3)
    print(t_normal)

# 3.均匀分布
# 在区间[0,1)上，生成均匀分布
# 标准均匀分布
# torch.rand()
# torch.rand_like()

# 在区间[low,high)上，生成整数均匀分布
# torch.randint()
# torch.randint_like()
# flag = True
flag = False
if flag:
    t_normal = torch.rand(2, 3)
    t_normal1 = torch.rand(size=(2, 3))
    # 两个是等效的
    print(t_normal)
    print(t_normal1)

    t_normal_int = torch.randint(2, 13, size=(5,))
    print(t_normal_int)

# 4.创建0到n-1的整数随机排列
# 常用来生成乱序索引
# torch.randperm()
# 返回1维张量
# flag = True
flag = False
if flag:
    t_normal = torch.randperm(5)
    print(t_normal)

# 4.伯努利分布/0-1分布/两点分布
'''torch.bernoulli(input,  # 概率值
                *,
                generator=None,
                out=None)'''
# 以input为概率
flag = True
# flag = False
if flag:
    input = torch.rand(1, 6)
    # input = torch.tensor([0., 0.2, 0., 0., 0.2, 0.])
    print(input)
    t_normal = torch.bernoulli(input)
    t_normal1 = torch.bernoulli(input, p=0)
    print(t_normal)
    print(t_normal1)
